﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;

namespace CSC.Google
{
    /// <summary>
    /// Dictionary of formatted rule results, with one entry for each Page Speed rule instantiated and run by the server.
    /// </summary>
    [Serializable, DebuggerDisplay("Count = {Count}")]
    public class RuleResults : ISerializable, IDictionary<string, RuleResult>
    {
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Dictionary<string, RuleResult> dict = new Dictionary<string, RuleResult>();
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private string content = string.Empty;

        /// <summary>
        /// Serialization method
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        protected RuleResults(SerializationInfo info, StreamingContext context)
        {
            foreach (SerializationEntry entry in info)
            {
                RuleResult array = entry.Value as RuleResult;
                dict.Add(entry.Name, array);
            }
        }

        /// <summary>
        /// Parses the rules
        /// </summary>
        private void ParseRuleResults()
        {
            List<RuleResult> data = new List<RuleResult>();
            List<string> keys = new List<string>();
            foreach (string key in this.dict.Keys)
            {
                keys.Add(key);
                int startIndex = content.IndexOf(key);
                int index = startIndex = content.IndexOf('{', startIndex);
                byte level = 0;
                while (level > 0 || index == startIndex)
                {
                    if (content[index] == '{') level++;
                    if (content[index] == '}') level--;
                    index++;
                }
                string part = content.Substring(startIndex, index - startIndex);
                using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(part)))
                {
                    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(RuleResult));
                    data.Add(jsonSerializer.ReadObject(ms) as RuleResult);
                    ms.Close();
                }
            }
            for (int i = 0; i < data.Count; i++) this.dict[keys[i]] = data[i];
            content = string.Empty;
        }

        /// <summary>
        /// Rule result
        /// </summary>
        /// <param name="key">The enum-like identifier for this rule, such as EnableKeepAlive or AvoidCssImport. Not localized.</param>
        /// <returns>Rule result</returns>
        public RuleResult this[string key] { get { return this.dict[key]; } set { throw new NotSupportedException(); } }

        /// <summary>
        /// The rule enum, such as Rule.EnableKeepAlive or Rule.AvoidCssImport.
        /// </summary>
        /// <param name="key"></param>
        /// <returns>Rule result</returns>
        public RuleResult this[Rule key] { get { return this.dict[key.ToString()]; } set { throw new NotSupportedException(); } }

        #region Interface Members
        public void GetObjectData(SerializationInfo info, StreamingContext context) { }
        public void Add(string key, RuleResult value) { this.dict.Add(key, value); }
        public bool ContainsKey(string key) { return this.dict.ContainsKey(key); }
        public ICollection<string> Keys { get { return this.dict.Keys; } }
        public bool Remove(string key) { return this.dict.Remove(key); }
        public bool TryGetValue(string key, out RuleResult value) { return this.dict.TryGetValue(key, out value); }
        public ICollection<RuleResult> Values { get { return this.dict.Values; } }
        public void Add(KeyValuePair<string, RuleResult> item) { throw new NotSupportedException(); }
        public void Clear() { throw new NotSupportedException(); }
        public bool Contains(KeyValuePair<string, RuleResult> item) { return this.dict.Contains(item); }
        public void CopyTo(KeyValuePair<string, RuleResult>[] array, int arrayIndex) { throw new NotSupportedException(); }
        public int Count { get { return this.dict.Count; } }
        public bool IsReadOnly { get { return true; } }
        public bool Remove(KeyValuePair<string, RuleResult> item) { return this.dict.Remove(item.Key); }
        public IEnumerator<KeyValuePair<string, RuleResult>> GetEnumerator() { return this.dict.GetEnumerator(); }
        IEnumerator IEnumerable.GetEnumerator() { return this.dict.GetEnumerator(); }
        #endregion
    }
}
